﻿using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Forms;
using System.Windows.Forms.VisualStyles;
using WPF_MVVM_PathSearchUtil.data_access;
using WPF_MVVM_PathSearchUtil.Models;
using WPF_MVVM_PathSearchUtil.util;
using WPF_MVVM_PathSearchUtil.ViewModels;
using WPF_MVVM_PathSearchUtil.Views;
using MessageBox = System.Windows.MessageBox;

namespace WPF_MVVM_PathSearchUtil.service
{
    public class MainWindowServiceImpl : MainWindowService
    {
        /// <summary>
        /// 抽出按钮事件
        /// </summary>
        /// <param name="fileList"></param>
        /// <param name="searchPath"></param>
        /// <param name="isChecked"></param>
        /// <returns></returns>
        public Resp WithdrawPath(ref ObservableCollection<FileInfoModel> fileList, string searchPath, bool isChecked)
        {
            if (searchPath == null || searchPath.Length <= 0)
            {
                return Resp.Fail("请输入要检索的路径。");
            }
            fileList.Clear();
            return getFileInfoList(ref fileList, searchPath, isChecked);

        }

        /// <summary>
        /// 获取输入路径内的所有文件列表
        /// </summary>
        /// <param name="fileList"></param>
        /// <param name="searchPath"></param>
        /// <param name="isChecked"></param>
        private Resp getFileInfoList(ref ObservableCollection<FileInfoModel> fileList, string searchPath, bool isChecked)
        {
            FileInfoModel fileInfoModel;
            if (searchPath.LastIndexOf('\\') != searchPath.Length - 1)
            {
                searchPath = searchPath + "\\";
            }
            DirectoryInfo directory = new DirectoryInfo(searchPath);
            if (directory.Exists)
            {
                FileInfo[] fileInfos;
                DirectoryInfo[] directoryInfos;
                fileInfos = directory.GetFiles("*", SearchOption.TopDirectoryOnly);
                directoryInfos = directory.GetDirectories("*", SearchOption.TopDirectoryOnly);
                foreach (FileInfo fileInfo in fileInfos)
                {
                    fileInfoModel = new FileInfoModel();
                    fileInfoModel.FileName = fileInfo.Name;
                    int index = fileInfo.FullName.LastIndexOf("\\");
                    fileInfoModel.FilePath = fileInfo.FullName.Substring(0, index + 1);
                    fileInfoModel.FileSize = Math.Round(Double.Parse(fileInfo.Length.ToString()) / 1024, 2);
                    fileInfoModel.FileType = fileInfo.Extension.Substring(1, fileInfo.Extension.Length - 1);
                    fileInfoModel.FileDate = fileInfo.CreationTime;
                    fileList.Add(fileInfoModel);
                }
                foreach (DirectoryInfo directoryInfo in directoryInfos)
                {
                    fileInfoModel = new FileInfoModel();
                    fileInfoModel.FileName = directoryInfo.Name;
                    int index = directoryInfo.FullName.LastIndexOf("\\");
                    fileInfoModel.FilePath = directoryInfo.FullName.Substring(0, index + 1);
                    fileInfoModel.FileSize = Math.Round(Double.Parse(GetDirectorySize(directoryInfo.FullName).ToString()) / 1024, 2);
                    fileInfoModel.FileType = "文件夹";
                    fileInfoModel.FileDate = directoryInfo.CreationTime;
                    fileList.Add(fileInfoModel);
                }
                if (isChecked)
                {

                    foreach (DirectoryInfo dirInfo in directoryInfos)
                    {
                        try
                        {
                            getFileInfoList(ref fileList, dirInfo.FullName, isChecked);
                        }
                        catch
                        {

                        }
                    }
                }
            }
            else
            {
                return Resp.Fail("目录不存在。");
            }
            return Resp.Success();
        }

        /// <summary>
        ///     获取文件夹的大小
        /// </summary>
        /// <param name="filePath"></param>
        /// <returns></returns>
        private static double GetDirectorySize(String filePath)
        {
            double size = 0;
            try
            {
                DirectoryInfo directory = new DirectoryInfo(filePath);
                FileInfo[] fileInfos = directory.GetFiles("*", SearchOption.TopDirectoryOnly);
                foreach (FileInfo fileInfo in fileInfos)
                {
                    size += fileInfo.Length;
                }
            }
            catch { }
            return size;
        }

        /// <summary>
        /// 检索关键字
        /// </summary>
        /// <param name="resultList"></param>
        /// <param name="fileList"></param>
        /// <param name="findWord"></param>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        public Resp Find(ref ObservableCollection<int> findResult, ObservableCollection<FileInfoModel> fileList, string findWord)
        {
            getFindResult(ref findResult, fileList, findWord, 0);
            if (findResult.Count <= 0)
            {
                getFindResult(ref findResult, fileList, findWord, 1);
            }
            if (findResult.Count <= 0)
            {
                return Resp.Fail("検索条件に一致するデータは見つかりません。");
            }
            return Resp.Success();
        }

        /// <summary>
        /// 检索下一个
        /// </summary>
        /// <param name="findResult"></param>
        /// <param name="fileList"></param>
        /// <param name="findWord"></param>
        /// <param name="indexNow"></param>
        /// <returns></returns>
        public Resp SearchNext(ref ObservableCollection<int> findResult, ObservableCollection<FileInfoModel> fileList, string findWord, int indexNow)
        {
            if (findResult.Count <= 0)
            {
                return Resp.Fail("当前没有要进行检索的关键字。");
            }
            if (findResult.Count == 1)
            {
                getFindResult(ref findResult, fileList, findWord, 1);
                if (findResult.Count == 1)
                {
                    return Resp.Fail("这已经是最后一条。");
                }
            }
            if (findResult.Count > 1)
            {
                int index = findResult.IndexOf(indexNow);
                if (index == findResult.Count - 1)
                {
                    return Resp.Success(findResult[0]);
                }
                else
                {
                    return Resp.Success(findResult[index + 1]);
                }
            }
            return Resp.Fail("fail");
        }

        /// <summary>
        /// 获取检索结果
        /// </summary>
        /// <param name="findResult"></param>
        /// <param name="fileList"></param>
        /// <param name="findWord"></param>
        /// <param name="findType">0 精确查找 1 模糊查找</param>
        private void getFindResult(ref ObservableCollection<int> findResult, ObservableCollection<FileInfoModel> fileList, string findWord, int findType)
        {
            findResult.Clear();
            for (int i = 0; i < fileList.Count; i++)
            {
                String fileName = fileList[i].FileName;
                if ((fileName.Equals(findWord) && findType == 0) ||
                    (fileName.IndexOf(findWord) >= 0 && findType == 1))
                {
                    findResult.Add(i);
                }
            }
        }

        /// <summary>
        /// 读取
        /// </summary>
        /// <param name="access"></param>
        /// <returns></returns>
        public Resp ReadByServerOrLocal(CSVReadOrWrite access, ref ObservableCollection<FileInfoModel> fileList)
        {
            if (access is LocalSQLite) {
                return ReadByLocal(access, ref fileList);
            }
            if (access is ServerSQLite)
            {
                return ReadByServer(access, ref fileList);
            }
            return Resp.Fail("fail");
        }

        /// <summary>
        /// 写入
        /// </summary>
        /// <param name="access"></param>
        /// <param name="fileList"></param>
        /// <returns></returns>
        public Resp WriteByServerOrLocal(CSVReadOrWrite access, ObservableCollection<FileInfoModel> fileListToWrite)
        {
            if (fileListToWrite.Count <= 0)
            {
                return Resp.Fail("没有可导出的列表。");
            }
            if (access is LocalSQLite)
            {
                return WriteByLocal(access, fileListToWrite);
            }
            if (access is ServerSQLite)
            {
                return WriteByServer(access, fileListToWrite);
            }
            return Resp.Fail("fail");
        }

        /// <summary>
        /// 服务端导出
        /// </summary>
        /// <param name="fileListToWrite"></param>
        /// <returns></returns>
        private Resp WriteByServer(CSVReadOrWrite access, ObservableCollection<FileInfoModel> fileListToWrite)
        {
            var fileData = new
            {
                fileList = fileListToWrite
            };
            Resp resp = access.Write("fileInfos/save", HttpMethod.Post, fileData);
            if (resp.Code != 0)
            {
                return Resp.Fail(resp.Message);
            }
            if (resp.Code == 0)
            {
                Dictionary<String, Object> response = (Dictionary<string, object>)resp.Date;
                if (Convert.ToInt64(response["code"]) == 0)
                {
                    return Resp.Success("导出成功。");
                }
                else
                {
                    return Resp.Fail("导出失败，" + response["message"].ToString());
                }
            }
            return Resp.Fail("fail");
        }

        /// <summary>
        /// 服务端读取
        /// </summary>
        /// <param name="access"></param>
        /// <param name="fileList"></param>
        /// <returns></returns>
        private Resp ReadByServer(CSVReadOrWrite access, ref ObservableCollection<FileInfoModel> fileList)
        {
            Resp resp = access.Read("fileInfos/get", HttpMethod.Get, null);
            if (resp.Code != 0)
            {
                return Resp.Fail(resp.Message);
            }
            else
            {
                Dictionary<String, Object> response = (Dictionary<string, object>)resp.Date;
                if (Convert.ToInt64(response["code"]) == 0)
                {
                    fileList.Clear();
                    JArray list = (JArray)response["data"];
                    ListConvertFromDB.JArrayToList(ref fileList, list);
                    return Resp.Success();
                }
                else
                {
                    return Resp.Fail("读取失败，" + response["message"].ToString());
                }
            }
        }

        /// <summary>
        /// 本地导出
        /// </summary>
        /// <param name="access"></param>
        /// <param name="fileListToWrite"></param>
        /// <returns></returns>
        private Resp WriteByLocal(CSVReadOrWrite access, ObservableCollection<FileInfoModel> fileListToWrite)
        {
            FolderBrowserDialog folderDlg = new FolderBrowserDialog();
            if (folderDlg.ShowDialog() == DialogResult.OK)
            {
                String exPath = folderDlg.SelectedPath;
                Resp resp = access.Write(exPath, fileListToWrite);
                if (resp.Code != 0)
                {
                    return Resp.Fail(resp.Message);
                }
                else
                {
                    return Resp.Success("成功，导出路径为：" + resp.Date);
                }
            }
            return Resp.Cancel();
        }

        /// <summary>
        /// 本地读取
        /// </summary>
        /// <param name="access"></param>
        /// <param name="fileList"></param>
        /// <returns></returns>
        private Resp ReadByLocal(CSVReadOrWrite access, ref ObservableCollection<FileInfoModel> fileList)
        {
            OpenFileDialog openFileDialog = new OpenFileDialog();
            if (openFileDialog.ShowDialog() == DialogResult.OK)
            {
                String imPath = openFileDialog.FileName;
                Resp resp = access.Read(imPath);
                if (resp.Code != 0)
                {
                    return Resp.Fail(resp.Message);
                }
                else
                {
                    fileList.Clear();
                    ListConvertFromDB.LocalToList(ref fileList, resp.Date);
                    return Resp.Success();
                }
            }
            return Resp.Cancel();
        }

        public Resp ToSort(ref ObservableCollection<FileInfoModel> fileList, ref int[] isDESC, DataGridSortingEventArgs e)
        {
            string header = (string)e.Column.Header;
            int columnIndex = -1;
            switch (header)
            {
                case "文件名": columnIndex = 0; break;
                case "路径": columnIndex = 1; break;
                case "类型": columnIndex = 2; break;
                case "大小": columnIndex = 3; break;
                case "日期": columnIndex = 4; break;
            }
            e.Handled = true;
            for (int i = 0; i < isDESC.Length; i++)
            {
                //当前点击列已排序，则反转list
                if (isDESC[columnIndex] == 1)
                {
                    isDESC[columnIndex] = 0;
                    List<FileInfoModel> fileInfoModels = new List<FileInfoModel>(fileList);
                    fileInfoModels.Reverse();
                    fileList.Clear();
                    ListToCollection.GetCollection(ref fileList, fileInfoModels);
                    return Resp.Success();
                }
            }
            List<FileInfoModel> fileInfos = new List<FileInfoModel>(fileList);
            if (columnIndex == 0)
            {
                fileInfos = fileInfos.OrderBy(x => x.FileName).ThenBy(z => z.FilePath).ToList();
            }
            if (columnIndex == 1)
            {
                fileInfos = fileInfos.OrderBy(x => x.FilePath).ThenBy(y => y.FileName).ToList();
            }
            if (columnIndex == 2)
            {
                fileInfos = fileInfos.OrderBy(x => x.FileType).ThenBy(y => y.FileName).ThenBy(z => z.FilePath).ToList();
            }
            if (columnIndex == 3)
            {
                fileInfos = fileInfos.OrderBy(x => x.FileSize).ThenBy(y => y.FileName).ThenBy(z => z.FilePath).ToList();
            }
            if (columnIndex == 4)
            {
                fileInfos = fileInfos.OrderBy(x => x.FileDate).ThenBy(y => y.FileName).ThenBy(z => z.FilePath).ToList();
            }
            //每次只能有一个列在排序
            for (int i = 0; i < isDESC.Length; i++)
            {
                isDESC[i] = 0;
            }
            isDESC[columnIndex] = 1;
            fileList.Clear();
            ListToCollection.GetCollection(ref fileList, fileInfos);
            return Resp.Success();
        }
    }
}
